import { Context } from 'koa';
import { User, IUserDocument } from '@/models';
import { BaseController } from './base.controller';
import { AppError } from '@/middlewares/error';
import { JwtUtil } from '@/utils/jwt';
import { SUCCESS_MESSAGES, ERROR_MESSAGES } from '@/constants';

/**
 * 用户控制器
 */
export class UserController extends BaseController {
  /**
   * 用户注册
   */
  async register(ctx: Context): Promise<void> {
    const userData = ctx.request.body as {
      username: string;
      email: string;
      password: string;
      firstName: string;
      lastName: string;
      phone?: string;
    };

    await this.handleAsync(async () => {
      // 检查邮箱是否已存在
      const existingUser = await User.findByEmail(userData.email);
      if (existingUser) {
        throw new AppError(ERROR_MESSAGES.EMAIL_ALREADY_EXISTS, 409);
      }

      // 检查用户名是否已存在
      const existingUsername = await User.findByUsername(userData.username);
      if (existingUsername) {
        throw new AppError('用户名已存在', 409);
      }

      // 创建新用户
      const user = new User({
        ...userData,
        role: 'user',
        status: 'pending',
      });

      // 生成邮箱验证令牌
      user.generateEmailVerificationToken();
      
      await user.save();

      // TODO: 发送邮箱验证邮件
      // await emailService.sendVerificationEmail(user.email, verificationToken);

      // 记录操作日志
      this.logAction('user_register', user.id, {
        email: user.email,
        username: user.username,
      });

      // 返回用户信息（不包含敏感数据）
      const userResponse = this.sanitizeResponse(user.toJSON());
      
      this.created(ctx, userResponse, SUCCESS_MESSAGES.CREATED);
    }, '用户注册失败');
  }

  /**
   * 用户登录
   */
  async login(ctx: Context): Promise<void> {
    const { email, password, rememberMe } = ctx.request.body as {
      email: string;
      password: string;
      rememberMe?: boolean;
    };

    await this.handleAsync(async () => {
      // 查找用户（包含密码字段）
      const user = await User.findOne({ email }).select('+password +loginAttempts +lockUntil');
      
      if (!user) {
        throw new AppError(ERROR_MESSAGES.INVALID_CREDENTIALS, 401);
      }

      // 检查账户状态
      if (user.status === 'suspended') {
        throw new AppError(ERROR_MESSAGES.ACCOUNT_SUSPENDED, 403);
      }

      if (user.status === 'deleted') {
        throw new AppError(ERROR_MESSAGES.USER_NOT_FOUND, 404);
      }

      // 检查账户是否被锁定
      if (user.isLocked()) {
        throw new AppError('账户已被锁定，请稍后再试', 423);
      }

      // 验证密码
      const isPasswordValid = await user.comparePassword(password);
      
      if (!isPasswordValid) {
        await user.incrementLoginAttempts();
        throw new AppError(ERROR_MESSAGES.INVALID_CREDENTIALS, 401);
      }

      // 登录成功，重置登录尝试次数
      user.resetLoginAttempts();
      user.lastLoginAt = new Date();
      await user.save();

      // 生成 JWT 令牌
      const tokenPayload = {
        id: user.id,
        email: user.email,
        role: user.role,
      };

      const token = JwtUtil.generateToken(tokenPayload);

      // 记录操作日志
      this.logAction('user_login', user.id, {
        email: user.email,
        ip: ctx.ip,
        userAgent: ctx.headers['user-agent'],
      });

      // 返回用户信息和令牌
      const userResponse = this.sanitizeResponse(user.toJSON());
      
      this.success(ctx, {
        user: userResponse,
        token,
        expiresIn: rememberMe ? '30d' : '7d',
      }, SUCCESS_MESSAGES.LOGIN_SUCCESS);
    }, '用户登录失败');
  }

  /**
   * 获取当前用户信息
   */
  async getCurrentUserInfo(ctx: Context): Promise<void> {
    const currentUser = this.requireAuth(ctx);

    await this.handleAsync(async () => {
      const user = await User.findById(currentUser.id);
      
      if (!user) {
        throw new AppError(ERROR_MESSAGES.USER_NOT_FOUND, 404);
      }

      const userResponse = this.sanitizeResponse(user.toJSON());
      this.success(ctx, userResponse, '获取用户信息成功');
    }, '获取用户信息失败');
  }

  /**
   * 更新用户信息
   */
  async updateProfile(ctx: Context): Promise<void> {
    const currentUser = this.requireAuth(ctx);
    const updateData = ctx.request.body as Partial<IUserDocument>;

    await this.handleAsync(async () => {
      const user = await User.findById(currentUser.id);
      
      if (!user) {
        throw new AppError(ERROR_MESSAGES.USER_NOT_FOUND, 404);
      }

      // 如果更新邮箱，需要检查唯一性
      if (updateData.email && updateData.email !== user.email) {
        const existingUser = await User.findOne({ email: updateData.email });
        if (existingUser) {
          throw new AppError(ERROR_MESSAGES.EMAIL_ALREADY_EXISTS, 409);
        }
        user.emailVerified = false;
        user.generateEmailVerificationToken();
      }

      // 如果更新用户名，需要检查唯一性
      if (updateData.username && updateData.username !== user.username) {
        const existingUsername = await User.findOne({ username: updateData.username });
        if (existingUsername) {
          throw new AppError('用户名已存在', 409);
        }
      }

      // 更新允许的字段
      const allowedFields = [
        'username', 'email', 'firstName', 'lastName', 'phone',
        'bio', 'dateOfBirth', 'gender', 'location', 'website'
      ];

      allowedFields.forEach(field => {
        if (updateData[field as keyof IUserDocument] !== undefined) {
          (user as any)[field] = updateData[field as keyof IUserDocument];
        }
      });

      await user.save();

      // 记录操作日志
      this.logAction('user_profile_update', user.id, {
        updatedFields: allowedFields.filter(field => 
          updateData[field as keyof IUserDocument] !== undefined
        ),
      });

      const userResponse = this.sanitizeResponse(user.toJSON());
      this.success(ctx, userResponse, SUCCESS_MESSAGES.UPDATED);
    }, '更新用户信息失败');
  }

  /**
   * 修改密码
   */
  async changePassword(ctx: Context): Promise<void> {
    const currentUser = this.requireAuth(ctx);
    const { currentPassword, newPassword } = ctx.request.body as {
      currentPassword: string;
      newPassword: string;
    };

    await this.handleAsync(async () => {
      const user = await User.findById(currentUser.id).select('+password');
      
      if (!user) {
        throw new AppError(ERROR_MESSAGES.USER_NOT_FOUND, 404);
      }

      // 验证当前密码
      const isCurrentPasswordValid = await user.comparePassword(currentPassword);
      
      if (!isCurrentPasswordValid) {
        throw new AppError('当前密码错误', 400);
      }

      // 更新密码
      user.password = newPassword;
      await user.save();

      // 记录操作日志
      this.logAction('user_password_change', user.id, {
        ip: ctx.ip,
        userAgent: ctx.headers['user-agent'],
      });

      this.success(ctx, null, SUCCESS_MESSAGES.PASSWORD_CHANGED);
    }, '修改密码失败');
  }

  /**
   * 获取用户列表（管理员功能）
   */
  async getUsers(ctx: Context): Promise<void> {
    this.requireAdmin(ctx);

    await this.handleAsync(async () => {
      const paginationQuery = this.getPaginationQuery(ctx);
      const filter = this.getQueryFilter(ctx, ['status', 'role']);
      
      // 构建搜索查询
      const searchQuery = this.buildSearchQuery(
        paginationQuery.keyword || '',
        ['username', 'email', 'firstName', 'lastName']
      );

      // 合并过滤条件
      const finalFilter = { ...filter, ...searchQuery };
      
      // 排序
      const sort = this.buildSort(
        paginationQuery.sortBy || 'createdAt', 
        paginationQuery.sortOrder || 'desc'
      );

      // 分页查询
      const result = await (User as any).paginate({
        page: paginationQuery.page,
        limit: paginationQuery.limit,
        filter: finalFilter,
        sort,
      });

      // 清理响应数据
      const sanitizedData = result.data.map((user: any) => 
        this.sanitizeResponse(user.toJSON())
      );

      this.paginated(ctx, {
        data: sanitizedData,
        pagination: result.pagination,
      }, '获取用户列表成功');
    }, '获取用户列表失败');
  }

  /**
   * 获取用户详情（管理员功能）
   */
  async getUserById(ctx: Context): Promise<void> {
    this.requireAdmin(ctx);
    const { id } = ctx.params;

    if (!id) {
      throw new AppError('缺少用户ID', 400);
    }

    this.validateId(id);

    await this.handleAsync(async () => {
      const user = await User.findById(id);
      
      if (!user) {
        throw new AppError(ERROR_MESSAGES.USER_NOT_FOUND, 404);
      }

      const userResponse = this.sanitizeResponse(user.toJSON());
      this.success(ctx, userResponse, '获取用户详情成功');
    }, '获取用户详情失败');
  }

  /**
   * 更新用户状态（管理员功能）
   */
  async updateUserStatus(ctx: Context): Promise<void> {
    this.requireAdmin(ctx);
    const { id } = ctx.params;
    const { status, reason } = ctx.request.body as {
      status: string;
      reason?: string;
    };

    if (!id) {
      throw new AppError('缺少用户ID', 400);
    }

    this.validateId(id);

    await this.handleAsync(async () => {
      const user = await User.findById(id);
      
      if (!user) {
        throw new AppError(ERROR_MESSAGES.USER_NOT_FOUND, 404);
      }

      const oldStatus = user.status;
      user.status = status as any;
      await user.save();

      // 记录操作日志
      this.logAction('user_status_update', id, {
        oldStatus,
        newStatus: status,
        reason,
        adminId: this.getCurrentUser(ctx)?.id,
      });

      const userResponse = this.sanitizeResponse(user.toJSON());
      this.success(ctx, userResponse, '用户状态更新成功');
    }, '更新用户状态失败');
  }

  /**
   * 删除用户（管理员功能）
   */
  async deleteUser(ctx: Context): Promise<void> {
    this.requireAdmin(ctx);
    const { id } = ctx.params;

    if (!id) {
      throw new AppError('缺少用户ID', 400);
    }

    this.validateId(id);

    await this.handleAsync(async () => {
      const user = await User.findById(id);
      
      if (!user) {
        throw new AppError(ERROR_MESSAGES.USER_NOT_FOUND, 404);
      }

      // 软删除
      user.status = 'deleted';
      user.deletedAt = new Date();
      await user.save();

      // 记录操作日志
      this.logAction('user_delete', id, {
        adminId: this.getCurrentUser(ctx)?.id,
      });

      this.success(ctx, null, SUCCESS_MESSAGES.DELETED);
    }, '删除用户失败');
  }

  /**
   * 用户统计（管理员功能）
   */
  async getUserStats(ctx: Context): Promise<void> {
    this.requireAdmin(ctx);

    await this.handleAsync(async () => {
      const [
        totalUsers,
        activeUsers,
        inactiveUsers,
        pendingUsers,
        newUsersThisMonth
      ] = await Promise.all([
        User.countDocuments({ status: { $ne: 'deleted' } }),
        User.countDocuments({ status: 'active' }),
        User.countDocuments({ status: 'inactive' }),
        User.countDocuments({ status: 'pending' }),
        User.countDocuments({
          status: { $ne: 'deleted' },
          createdAt: {
            $gte: new Date(new Date().getFullYear(), new Date().getMonth(), 1)
          }
        })
      ]);

      const stats = {
        total: totalUsers,
        active: activeUsers,
        inactive: inactiveUsers,
        pending: pendingUsers,
        newThisMonth: newUsersThisMonth,
      };

      this.success(ctx, stats, '获取用户统计成功');
    }, '获取用户统计失败');
  }
}

export default UserController;